home *** CD-ROM | disk | FTP | other *** search
- /* DSHERC.C
-
- Sample ADI device driver for use as model in driver development.
-
- Configurator and display driver for the Hercules display board on
- the IBM PC. Split-screen configuration.
-
- */
-
- /* #define DEBUG 1 */
-
- /* If DUMB is defined, this driver will act as a very stupid display
- and make AutoCAD do all its tricks to restore things on mode
- switches. */
-
- /* #define DUMB 1 */
-
- /* If SMART is defined, this driver will include test code to exercise
- the "extended functions" SYNC and REDRAW. It doesn't really do them.
- It is imprudent to set both SMART and DUMB at the same time. */
-
- /* #define SMART 1 */
-
- #include <stdio.h>
-
- #define VERSION "1.10"
- #define REVDATE "10/28/86"
- #define FALSE 0
- #define TRUE 1
-
- /* Default interrupt vector for display drivers is 0x7A. This is
- selectable by user during AutoCAD configuration. */
-
- #define VECTOR 0x7A /* Interrupt vector used for messages */
-
- #define YSIZE 348
- #define XSIZE 720
-
- #define BASE6845 0x3B4 /* CRT controller base address. */
- #define ADRREG BASE6845
- #define DATAREG (BASE6845+1)
- #define CTLREG (BASE6845+4)
- #define STATREG (BASE6845+6)
- #define CFGREG (BASE6845+11) /* configuration register */
- #define INITL 14 /* Number of CRTC regs to initialize. */
- #define NSYNC 6 /* Number of vsyncs to wait on mode switch */
- #define TEXTSEG 0xB000 /* vram base for text screen. */
- #define MCHARS 8 /* Characters in a menu box. */
- #define CHARHGT 14 /* Character height in pixels. */
- #define CHARWID 9 /* Character width. */
- #define XMENUMIN (XSIZE-CHARWID*MCHARS) /* Left margin of menu box. */
- #define XMAX (XMENUMIN-6) /* Right margin of graphics area. */
- #define SPLIT 3 /* Lines in split-text area. */
- #define SPLITHGT (CHARHGT*SPLIT+7) /* Split-text area height. */
- #define YSPLIT (YSIZE-SPLIT*CHARHGT) /* Row nr of text area */
- #define XCLINE (9*40) /* Start of coordinate display line. */
-
- #define msb(v) ((v >> 8) & 0xFF)
- #define lsb(v) (v & 0xFF)
- #define packbyte(x, y) ((x << 8) | y)
-
- /* BIOS interrupt numbers and subfunctions: */
-
- #define VIDEO_IO 0x10
- #define SCURSOR 2 /* Set cursor */
- #define SCROLL_UP 6 /* Scroll active page up */
-
- /* Request codes */
-
- #define INIT1 1 /* Initialise parameters 1 */
- #define INIT2 2 /* Initialise parameters 2 */
- #define INIT3 3 /* Initialise parameters 3 */
- #define INIT4 4 /* Initialise parameters 4 */
- #define INIT5 5 /* Initialise parameters 5 */
- #define TERM 9 /* Terminate */
-
- #define CLEAR 10 /* Clear graphics screen */
- #define DOT 11 /* Complement dot */
- #define MOVE 12 /* Set screen cursor */
- #define DRAW 13 /* Draw line */
- #define FLOOD 14 /* Solid fill vertex / point */
- #define MARK 15 /* Draw graphic cursor */
- #define CMARK 16 /* Clear graphic cursor */
-
- #define CHAR 20 /* Draw character on graphics screen */
- #define ECHAR 21 /* End character string */
- #define MHLITE 22 /* Menu highlight */
- #define MDHLITE 23 /* Menu de-highlight */
- #define MNUCUR 24 /* Set character address to box */
-
- #define TPROMPT 30 /* Set character address to prompt line */
- #define QPLOT 31 /* Screen dump */
- #define RPEN 32 /* Read pen */
- #define GOTEXT 33 /* Go to text screen */
- #define GOTEXTU 34 /* Go to text screen - user request */
- #define GOGRAPH 35 /* Go to graphics screen */
- #define WRSPLIT 36 /* Write to split screen */
- #define MODELINE 37 /* Write to mode line */
- #define COORDL 38 /* Write to coordinate line */
-
- #define SYNC 50 /* Flush display buffers */
- #define REDRAW 51 /* Driver-local redraw */
-
- /* Configuration bits */
-
- #define CF_TEXT 1 /* Draw text scrolling area */
- #define CF_MENU 2 /* Draw screen menu */
- #define CF_STATUS 4 /* Draw status line */
-
- /* Repaint control bits */
-
- #define RP_STAT 1 /* Repaint status line */
- #define RP_MENU 2 /* Repaint status line */
- #define RP_SCROLL 4 /* Repaint scroll area */
- #define RP_GRAPH 8 /* Redraw picture */
-
- /* Driver mode bits */
-
- #define DM_CCECH 1 /* Suppress echo of control C */
- #define DM_HLEN 2 /* Driver can do highlighting */
- #define DM_GROK 4 /* Driver is single screen */
-
- /* Extended function enable bits */
-
- #define EF_SYNC 1 /* Enable SYNC function */
- #define EF_REDRAW 2 /* Enable REDRAW function */
-
- /****** Global symbols exported (to DSHERCA) ******/
-
- short graphx, graphy; /* Graphics area width and height. */
- short color; /* Current colour */
- short hilight; /* Highlight flag */
- short cline; /* Status line configured */
-
- /****** Local stuff ******/
-
- /* Initial values for CRTC registers R0-R13 */
- static char
- graphinit[INITL] = {
- 56,45,48, 8,90,0,87,87,2, 3, 0, 0,0,0}
- ,
- textinit[INITL] = {
- 97,80,82,15,25,6,25,25,2,13,0,14,0,0};
-
- static short tcursx,tcursy; /* Text cursor position */
- static int splitchar = 0, /* Characters in current line. */
- splitline = YSPLIT, /* Line we're writing on. */
- splitdirty = 0;/* Any characters on line flag. */
- static short ybias; /* To convert shorts to hard coords. */
- static short notxt, nomnu; /* Configuration status */
- static short ixdots, iydots, ixdotsm, modelinl, mnuchars,
- maxboxes, hlenab, graphok, hwfill;
-
- struct pregs { /* Structure to communicate with ACAD */
- short code, arg1, arg2, arg3;
- };
- static struct pregs c; /* Master communication structure */
-
- extern char inp();
- unsigned r6845();
-
- extern long _psp, _mnext;
- extern unsigned _tsize;
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- short i, cl;
- short lx, ly;
-
- #ifdef DEBUG
- printf("\n Mnext = %08lx _Psp = %08lx _tsize = %04x",
- _mnext, _psp, _tsize);
- #endif
-
- printf("\n--- Autodesk Device Interface/ADI Driver ---");
-
- #ifdef DUMB
- printf("\nDumb ADI graphics board driver Vers. %s installed as INT %03xh.",
- #else
- printf("\nHercules Graphics Board driver Vers. %s installed as INT %03xh.",
- #endif
- VERSION,VECTOR);
- #ifdef SMART
- printf("\nSmart display debugging features enabled.");
- #endif
-
- printf("\nSample ADI Driver created %s by Autodesk, Inc.\n",REVDATE);
-
- /* ADI driver developer should include name of company, or company and
- individual, responsible for creation of ADI device driver and date
- of driver creation to aid in identifying driver. */
-
- while (TRUE) {
- iwait(VECTOR, &c, &c);
-
- /* Dispatch commands received from active program */
-
- #ifdef DUMPCMD
- if (c.code != 32) { /* Skip pen probes */
- if (c.code == 20 || c.code == 36)
- putchar(c.arg1);
- else
- printf("\n ** Display(%d): %d, %d, %d **",
- c.code, c.arg1, c.arg2, c.arg3);
- }
- #endif
-
- switch (c.code) {
-
- case INIT1:
- notxt = !(c.arg1 & CF_TEXT);
- nomnu = !(c.arg1 & CF_MENU);
- cline = !!(c.arg1 & CF_STATUS);
- ixdotsm = XSIZE - 1;
- ixdots = nomnu ? XSIZE - 1 : XMAX;
- graphx = (ixdots + 1); /* Graphics area width. */
-
- /* YBIAS: "natural" y-coordinate of screen coord origin. Also
- number of pixels vertically in menu area. */
-
- ybias = iydots = notxt ? YSIZE - 1 : YSIZE - 1 - SPLITHGT;
- if (cline)
- iydots -= CHARHGT; /* Status line correction. */
- modelinl = XCLINE/9; /* Mode line length. */
- graphy = iydots + 1; /* Graphics area height. */
- mnuchars = MCHARS;
- maxboxes = nomnu ? 0 : (ybias+1) / CHARHGT;
- hwfill = 0; /* No hardware fill */
- hlenab = 1; /* Driver knows how to highlight */
- graphok = 1; /* Graphics mode ok now. */
-
- c.code = TRUE;
- c.arg1 = ixdots;
- c.arg2 = iydots;
- c.arg3 = ixdotsm;
- break;
-
- case INIT2:
- c.arg1 = packbyte(modelinl, mnuchars);
- #ifdef DUMB
- c.arg2 = packbyte(maxboxes, DM_HLEN | DM_GROK | DM_CCECH);
- #else
- c.arg2 = packbyte(maxboxes, DM_HLEN | DM_GROK);
- #endif
- c.arg3 = packbyte(SPLIT, hwfill);
- break;
-
- case INIT3:
- #ifdef DEBUG
- printf("\nINIT3: notxt %d nomnu %d cline %d ixdots %d iydots %d",
- notxt, nomnu, cline, ixdots, iydots);
- printf("\n graphx %d graphy %d ybias %d modelinl %d",
- graphx, graphy, ybias, modelinl);
- printf("\n mnuchars %d maxboxes %d hwfill %d hlenab %d",
- mnuchars, maxboxes, hwfill, hlenab);
- printf("\n graphok %d\n", graphok);
- #endif
- outp(CFGREG,3); /* Enable graphics mode, page1 */
- adswipe(); /* Clear the (invisible) graphics screen */
- gograph(); /* Go to graphics mode. */
- drawbord(); /* Draw the borders */
-
- c.arg1 = 5556; /* X pixel spacing */
- c.arg2 = 8621; /* Y pixel spacing */
- #ifdef DUMB
- c.arg3 = packbytes(25, 80);
- #else
- c.arg3 = 0;
- #endif
- break;
-
- case INIT4:
- c.arg1 = 0; /* No extended functions */
- #ifdef SMART
- c.arg2 = EF_SYNC | EF_REDRAW;
- #else
- c.arg2 = 0; /* for now, thanks */
- #endif
- break;
-
- case INIT5:
- c.arg1 = iydots; /* Ymenumax = iydots */
- c.arg2 = YSIZE - 1; /* iydotsm */
- break;
-
- case TERM:
- break;
-
- case CLEAR:
- #ifdef DUMB
- adswipe();
- drawbord();
- c.arg1 = RP_MENU | RP_STAT | RP_SCROLL;
- #else
- adsclr();
- c.arg1 = 0;
- #endif
- break;
-
- case DOT:
- adsdot(c.arg1, ybias - c.arg2);
- break;
-
- case MOVE:
- lx = c.arg1;
- ly = c.arg2;
- hilight = c.arg3 & 1;
- break;
-
- case DRAW:
- #ifdef DUMPCMD
- printf("\nDraw (%d,%d) - (%d,%d) in %d",
- lx, ly, c.arg1, c.arg2, c.arg3);
- #endif
- if (c.arg3 >= 0) {
- color = c.arg3;
- adsvec(lx, ybias - ly, c.arg1, ybias - c.arg2);
- }
- else
- adsxvec(lx, ybias - ly, c.arg1, ybias - c.arg2);
- break;
-
- case FLOOD:
- break;
-
- case MARK:
- case CMARK:
- if (c.arg3 == 0 || c.arg3 == 3) {
- adsmark(c.arg1, ybias - c.arg2);
- c.code = TRUE;
- }
- else
- c.code = FALSE;
- break;
-
- case CHAR:
- if (tcursx <= (XSIZE-CHARWID))
- adschar(tcursx, tcursy, c.arg1);
- tcursx += CHARWID;
- break;
-
- case ECHAR:
- break;
-
- case MHLITE:
- case MDHLITE:
- for (i = 0, cl = tcursx; i < MCHARS; i++) {
- dsrvid(cl, tcursy); /* Invert all the characters. */
- cl += CHARWID;
- }
- c.arg1 = FALSE; /* Say characters not needed */
- break;
-
- case MNUCUR:
- i = (ybias + 1) / c.arg2;
- tcursx = XMENUMIN;
- tcursy = (ybias + 1 - CHARHGT) - (c.arg2 - c.arg1 - 1) * i;
- break;
-
- case TPROMPT:
- break;
-
- case QPLOT:
- break;
-
- case RPEN:
- c.arg1 = 0;
- break;
-
- case GOTEXT:
- gotext();
- break;
-
- case GOTEXTU:
- gotextu();
- #ifdef DUMB
- txclr();
- #endif
- break;
-
- case GOGRAPH:
- gograph();
- #ifdef DUMB
- adswipe();
- c.arg1 = RP_GRAPH | RP_MENU | RP_STAT | RP_SCROLL;
- #else
- c.arg1 = 0;
- #endif
- break;
-
- case WRSPLIT:
- wrsplit(c.arg1);
- break;
-
- case MODELINE:
- tcursx = tcursy = 0;
- adschar(tcursx, tcursy, 'C');
- tcursx += CHARWID;
- adschar(tcursx, tcursy, c.arg2 + '0'); /* Colour */
- tcursx += CHARWID;
- adschar(tcursx, tcursy, ' ');
- tcursx += CHARWID;
- break;
-
- case COORDL:
- tcursx = XCLINE;
- tcursy = 0;
- break;
-
- #ifdef SMART
- case SYNC:
- printf(" <sync> ");
- break;
-
- case REDRAW:
- printf(c.arg1 ? " <clear> " : " <redraw> ");
- c.code = FALSE;
- break;
- #endif
-
- default:
- printf("\n** Unimplemented display command code %d **\n",
- c.code);
- c.code = FALSE;
- }
- }
- }
-
- static gograph()
- {
- int cursor, splitbase, i;
- char rch;
-
- modeinit(0x82, graphinit);/* Put the CRTC in graphics mode. */
- if (notxt) /* Graphics text configured off? */
- return;
-
- /* Copy the bottom SPLIT lines on the text screen into the text
- area of the graphics screen. Start by finding address within
- text screen buffer of first character to copy (note that the
- text buffer has two bytes per displayed character). */
-
- cursor = r6845(14) << 1; /* Cursor address from CRTC. */
- splitbase = cursor - cursor%160 - ((SPLIT-1)*160);
- if (splitbase < 0) splitbase = 0;
-
- clearsplit(); /* Clear text area on graphics screen. */
- #ifndef DUMB
- for (i = splitbase; i < cursor; i += 2) { /* Read character from */
- peek(TEXTSEG, i, &rch, 1);
- wrsplit1(rch); /* text screen, copy to graphics. */
- }
- #endif
- }
-
-
- /* Go into text mode if not already there, with a clear screen. */
-
- static gotext()
- {
- txclr();
- gotextu(); /* Switch modes. */
- }
-
-
- /* Go into text mode at user request (show hidden text). */
-
- static gotextu()
- {
- modeinit(0, textinit); /* Make the mode switch. */
- }
-
-
- /* Write a character to the graphics screen text area and save it in
- in "hidden" text. */
-
- static wrsplit(c)
- char c;
- {
- wrsplit1(c);
- #ifndef DUMB
- putchar(c); /* Let OS write to hidden screen. */
-
- #endif
- }
-
- /* Write a character to the graphics screen text area. */
-
- static wrsplit1(c)
- char c;
- {
- if (notxt)
- return; /* No graphics text area. */
-
- switch (c) {
- case '\r': /* Carriage return */
- splitchar = 0;
- break;
- case '\n': /* Line feed. */
- if (splitdirty) /* Unless current line is blank, */
- {
- splitline += CHARHGT; /* advance to next. */
- splitdirty = 0;
- }
- break;
- case '\t': /* tab (does better than DOS!) */
- do
- wrsplit1(' ');
- while (splitchar & 7);
- break;
- case '\b': /* backspace. */
- if (splitchar > 0)
- splitchar -= CHARWID;
- break;
- default: /* Normal character. */
- if (splitchar >= XSIZE) /* If off end of line, */
- {
- wrsplit1('\r'); /* do a line feed. */
- wrsplit1('\n');
- }
- adschar(splitchar, splitline, c); /* Draw it. */
- splitchar += CHARWID; /* Update cursor. */
- splitdirty = 1; /* Non-blank line. */
- }
-
- if (splitline >= YSIZE) /* If off bottom of screen, */
- {
- hcscroll(SPLIT); /* scroll up. */
- splitline -= CHARHGT;
- }
- }
-
- /* Initialize the CRTC in a new mode. ctlbits is the value to be
- put into the CRT control register, and should not include the
- enable-video bit. */
-
- static modeinit(ctlbits, initstr)
- char ctlbits, *initstr;
- {
- int i;
-
- outp(CTLREG, ctlbits); /* Disable video signal. */
- for (i = 0; i < INITL; i++) /* Load 6845 registers. */
- {
- outp(ADRREG, i); /* Point to reg. #i */
- outp(DATAREG, *initstr++); /* Send it its value. */
- }
-
- for (i = -1; ++i < NSYNC; ) /* Wait until vertical sync */
- {
- while (~inp(STATREG) & 0x80) ; /* goes low for the */
- while (inp(STATREG) & 0x80) ; /* NSYNCHth time */
- }
- outp(CTLREG, ctlbits | 8);/* to re-enable video. */
- }
-
- /* Routine to read a 16-bit CRTC register. */
-
- static unsigned int r6845(r)
- int r;
- {
- char r1, r0;
-
- outp(ADRREG, r++); /* Point to the register. */
- r1 = inp(DATAREG); /* Read high byte. */
- outp(ADRREG, r); /* Point to next register. */
- r0 = inp(DATAREG); /* Read low byte. */
- return (unsigned int)r0 | ((unsigned int)r1 << 8); /* Return both. */
- }
-
- /* TXCLR -- Clear the text screen */
-
- static txclr()
- {
- /* Call BIOS to scroll screen clear. */
- ibmbios(VIDEO_IO, SCROLL_UP, 0, 0x184F, 0, 0x700);
-
- /* Now have it set the cursor to upper left corner. */
- ibmbios(VIDEO_IO, SCURSOR, 0, 0, 0, 0);
- }
-
- /* DRAWBORD -- Draw borders on graphics screen */
-
- static drawbord()
- {
- short i;
-
- /* Draw the borders */
-
- color = 7;
- if (!notxt)
- for (i = 0; i-- > -2; ) /* Horizontal */
- adsvec(0, ybias - i, ixdotsm, ybias - i);
-
- if (!nomnu)
- for (i = XMAX; i++ < (XMAX + 2); ) /* Vertical */
- adsvec(i, ybias, i, 0);
- }
-
- /* Clear the graphics text area and reset its insertion cursor. */
-
- static clearsplit()
- {
- int i;
-
- #ifndef DUMB
- for (i=0; i<SPLIT; i++) /* All these scrolls will */
- hcscroll(SPLIT); /* clear the area. */
- #endif
-
- /* Set insertion cursor to SPLIT lines above screen bottom */
- splitchar = 0;
- splitline = YSPLIT;
- }
-
-
-